package org.contextsensitivetodo.context;

import java.util.LinkedList;

import org.contextsensitivetodo.context.rules.ContextRule;
import org.contextsensitivetodo.context.rules.ContextRuleStateChangeListener;
import org.contextsensitivetodo.context.rules.ContextRuleStateChangedEvent;
import org.contextsensitivetodo.context.rules.location.LocationContextRule;

import android.location.Location;
import android.util.Log;

public class UserContext{

	private String name;
	private LinkedList<ContextRule> contextRules = new LinkedList<ContextRule>();

	private boolean currentState = false;

	private LinkedList<ContextStateChangeListener> listeners = new LinkedList<ContextStateChangeListener>();

	private ContextRuleStateChangeListener ruleListener = new ContextRuleStateChangeListener() {

		public void handleContextRuleStateChanged(ContextRuleStateChangedEvent e) {
			setCurrentState();
		}
	};

	public void addContextRule(ContextRule newRule) {
		this.contextRules.add(newRule);
		newRule.addContextRuleStateChangeListener(this.ruleListener);
	}

	public boolean isOn() {
		return currentState;
	}

	private void setCurrentState() {
		for (ContextRule rule : contextRules) {
			if (!rule.isOn()) {
				this.setNewState(false);
				return;
			}
		}
		this.setNewState(true);
	}

	private void setNewState(boolean newState) {
		if (newState != this.currentState) {
			this.currentState = newState;
			this.fireEvent(!this.currentState, this.currentState);
		}
	}

	public String getName() {
		return name;
	}

	public void setName(String name) {
		this.name = name;
	}

	public void addContextRuleStateChangeListener(
			ContextStateChangeListener listener) {
		this.listeners.add(listener);

	}

	public void removeContextRuleStateChangeListener(
			ContextStateChangeListener listener) {
		this.listeners.remove(listener);
	}

	public void fireEvent(boolean oldState, boolean newState) {
		Log.d("cstodo", "*** User Context state change detected!");
		
		ContextStateChangedEvent event = new ContextStateChangedEvent(this,
				oldState, newState);

		for (ContextStateChangeListener listener : this.listeners) {
			listener.handleContextStateChanged(event);

		}
	}
	
	public void doStateUpdate(){
		doStateUpdate(null);
	}
	
	
	public void doStateUpdate(Location newLocation){
		Log.d("cstodo", "Contect " + this.getName() + " update triggered");
		for (ContextRule rule : contextRules) {
			if(rule instanceof LocationContextRule){
				if(newLocation != null){
					((LocationContextRule)rule).doStateUpdate(newLocation);
				}
			}else{
				rule.doStateUpdate();
			}
			
			
		}
		Log.d("cstodo", "contex rules all updated");
	}
	
	@Override
	public String toString() {
		StringBuffer sb = new StringBuffer();
		sb.append("User context "+ this.getName() + "\nContext rules:\n");
		
		for (ContextRule rule : this.contextRules) {
			sb.append(rule.getRuleName() + ": " + rule.isOn()+"\n");
			
		}
		
		
		return sb.toString();
	}

}
